package top.kangyaocoding.ecommerce.controller;

import io.github.resilience4j.ratelimiter.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.kangyaocoding.ecommerce.IUsersService;
import top.kangyaocoding.ecommerce.constants.Constants;
import top.kangyaocoding.ecommerce.dto.EditUsersDTO;
import top.kangyaocoding.ecommerce.dto.UsersDTO;
import top.kangyaocoding.ecommerce.impl.RateLimiterService;
import top.kangyaocoding.ecommerce.req.AuthReq;
import top.kangyaocoding.ecommerce.req.UserReq;
import top.kangyaocoding.ecommerce.response.Response;
import top.kangyaocoding.ecommerce.utils.JwtUtil;

import java.util.Collections;
import java.util.List;

/**
 * 描述: 用户控制层
 *
 * @author K·Herbert
 * @since 2025-02-19 下午3:12
 */
@Slf4j
@RestController
@RequestMapping("/users")
@CrossOrigin("*")
public class UsersController {

    private final RateLimiterService rateLimiterService;
    private final IUsersService usersService;
    private final JwtUtil jwtUtil;

    public UsersController(RateLimiterService rateLimiterService, IUsersService usersService, JwtUtil jwtUtil) {
        this.rateLimiterService = rateLimiterService;
        this.usersService = usersService;
        this.jwtUtil = jwtUtil;
    }

    @PostMapping("/loginByPassword")
    Response<String> loginByPassword(@RequestBody AuthReq request) throws Exception {
        String email = request.getEmail();
        String password = request.getPassword();
        if (StringUtils.isBlank(email) || StringUtils.isBlank(password)) {
            return Response.<String>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(null)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getLoginRateLimiter(email);

        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }

        return usersService.loginByPassword(email, password);
    }

    @PostMapping("/loginByVerificationCode")
    Response<String> loginByVerificationCode(@RequestBody AuthReq request) {
        String email = request.getEmail();
        String verificationCode = request.getVerificationCode();
        if (StringUtils.isBlank(email) || StringUtils.isBlank(verificationCode)) {
            return Response.<String>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(null)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getVerificationCodeLimiter(email);
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.loginByVerificationCode(email, verificationCode);
    }

    @PostMapping("/register")
    Response<Boolean> register(@RequestBody AuthReq request) {
        String email = request.getEmail();
        String password = request.getPassword();
        String verificationCode = request.getVerificationCode();
        if (StringUtils.isBlank(email) || StringUtils.isBlank(password) || StringUtils.isBlank(verificationCode)) {
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getGlobalRateLimiter();
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.register(email, password, verificationCode);
    }

    @PostMapping("/sendVerificationCode")
    void sendVerificationCode(@RequestParam("email") String email) {
        if (StringUtils.isBlank(email)) {
            log.error("发送验证码失败，邮箱为空");
            return;
        }
        RateLimiter rateLimiter = rateLimiterService.getGlobalRateLimiter();
        if (!rateLimiter.acquirePermission()) {
            log.error("获取验证码失败，请稍后重试");
            return;
        }
        usersService.sendVerificationCode(email);
    }

    @PostMapping("/getUserInfo")
    Response<UsersDTO> getUserInfo(@RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<UsersDTO>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(null)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getGlobalRateLimiter();
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.getUserInfo(token);
    }

    @PostMapping("/getUserEmailAndSendVerificationCode")
    Response<String> getUserEmailAndSendVerificationCode(@RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<String>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(null)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getUpdateLimiter("getUserEmailAndSendVerificationCode:" + token);
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.getUserEmailAndSendVerificationCode(token);
    }

    @PostMapping("/updateUserPassword")
    Response<Boolean> updateUserPassword(@RequestBody AuthReq request, @RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
        String email = request.getEmail();
        String verificationCode = request.getVerificationCode();
        String password = request.getPassword();
        if (StringUtils.isBlank(email) || StringUtils.isBlank(verificationCode) || StringUtils.isBlank(password)) {
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getUpdateLimiter("updateUserPassword:" + token);
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.updateUserPassword(email, verificationCode, password);
    }

    @PostMapping("/updateUserInfo")
    public Response<Boolean> updateUserInfo(@RequestBody UserReq request, @RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
        String nikeName = request.getNikeName();
        String biography = request.getBiography();
        if (StringUtils.isBlank(nikeName) || StringUtils.isBlank(biography)) {
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getUpdateLimiter("updateUserInfo:" + token);
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        try {
            return usersService.updateUserInfo(nikeName, biography, token);
        } catch (Exception e) {
            // 失败时返回错误信息
            log.error("更新用户信息失败: {}", e.getMessage());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.UN_ERROR.getCode())
                    .info(Constants.ErrorCode.UN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
    }

    @PostMapping("/updateUserAvatar")
    public Response<Boolean> updateUserAvatar(@RequestParam("file") MultipartFile file, @RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
        if (file.isEmpty()) {
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.ILLEGAL_PARAMETER.getCode())
                    .info(Constants.ErrorCode.ILLEGAL_PARAMETER.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getUpdateLimiter("updateUserAvatar:" + token);
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        try {
            return usersService.updateUserAvatar(file, token);
        } catch (Exception e) {
            // 失败时返回错误信息
            log.error("上传文件失败: {}", e.getMessage());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.UN_ERROR.getCode())
                    .info(Constants.ErrorCode.UN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
    }

    @PostMapping("/getUserList")
    Response<List<UsersDTO>> getUserList(@RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<List<UsersDTO>>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(Collections.emptyList())
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getGlobalRateLimiter();
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.getUserList(token);
    }

    @PostMapping("/editUser")
    Response<Boolean> editUser(@RequestBody EditUsersDTO request, @RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter rateLimiter = rateLimiterService.getGlobalRateLimiter();
        if (!rateLimiter.acquirePermission()) {
            return handleRateLimiter();
        }
        String email = request.getEmail();
        String status = request.getUserStatus();
        String role = request.getUserRole();
        return usersService.editUser(email, status, role, token);
    }

    @PostMapping("/resetPassword")
    Response<Boolean> resetPassword(@RequestParam("email") String email, @RequestHeader("Authorization") String token) {
        if (!jwtUtil.validateToken(token)) {
            log.error("Token 异常: {}", Constants.ErrorCode.TOKEN_ERROR.getInfo());
            return Response.<Boolean>builder()
                    .code(Constants.ErrorCode.TOKEN_ERROR.getCode())
                    .info(Constants.ErrorCode.TOKEN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
        RateLimiter limiter = rateLimiterService.getUpdateLimiter("resetPassword:" + token);
        if (!limiter.acquirePermission()) {
            return handleRateLimiter();
        }
        return usersService.resetPassword(email, token);
    }

    private <T> Response<T> handleRateLimiter() {
        return Response.<T>builder()
                .code(Constants.ErrorCode.TOO_MANY_REQUESTS.getCode())
                .info(Constants.ErrorCode.TOO_MANY_REQUESTS.getInfo())
                .data(null)
                .build();
    }

}
